package com.example.demo.testconcurrent.controller;


import com.example.demo.testconcurrent.entity.TestConcurrent;
import com.example.demo.testconcurrent.service.ITestConcurrentService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author gaobing
 * @since 2020-08-21
 */
@RestController
@RequestMapping("/concurrent")
@Slf4j
public class TestConcurrentController {

    @Autowired
    private ITestConcurrentService iTestConcurrentService;

    private static final int CONCURRENCE_COUNT = 100;

    private static CountDownLatch cd = new CountDownLatch(CONCURRENCE_COUNT);

    /**
     * 0-100累加,多线程更新数据库
     *
     * @return
     */
    @PostMapping("/accumulation")
    public boolean accumulation() {

        // 一千个线程，同时怼一个方法
        for (int i = 0; i < CONCURRENCE_COUNT; i++) {
            new Thread(new SendTask()).start();
            cd.countDown();
        }
        return true;
    }

    private Lock lock = new ReentrantLock();
    public class SendTask implements Runnable {

        @SneakyThrows
        @Override
        public void run() {
            log.info(Thread.currentThread().getName() + " 正在等待...");
            cd.await();

            lock.lock();
            try {
                log.info(Thread.currentThread().getName() + " 开始...");
                save();
            } finally {
               lock.unlock();
            }
        }
    }

    private void save() {
        TestConcurrent testConcurrent = iTestConcurrentService.getById(1);
        testConcurrent.setId(1);
        testConcurrent.setConcurrentCount(testConcurrent.getConcurrentCount() + 1);
        iTestConcurrentService.updateById(testConcurrent);
    }

}

